home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / v7n19.arc / TED.ASM < prev    next >
Assembly Source File  |  1988-10-14  |  47KB  |  1,547 lines

  1. ;======================================================================
  2. ;  TED.ASM -- The Tiny EDitor.
  3. ;  PC Magazine * Tom Kihlken * tktktk
  4. ;----------------------------------------------------------------------
  5. CSEG        SEGMENT
  6.         ASSUME    CS:CSEG, DS:CSEG, ES:CSEG
  7.         ORG    100H        ;Beginning for .COM programs
  8. START:
  9.         JMP    BEGIN
  10.  
  11. ;-----------------------------------------------------------------------
  12. ; Local data area
  13. ;-----------------------------------------------------------------------
  14. TAB        EQU    9
  15. CR        EQU    13
  16. LF        EQU    10
  17.  
  18. COPYRIGHT    DB    CR,LF,"TED 1.0 (c) 1988 Ziff Communications Co."
  19.         DB    CR,LF,"PC Magazine ",254," Tom Kihlken$",1AH
  20.  
  21. FILE_TOO_BIG    DB    "File too big$"
  22. READ_ERR_MESS    DB    "Read error$"
  23. MEMORY_ERROR    DB    "Not enough memory$"
  24.  
  25. PROMPT_STRING    DB    "1ABORT",0,"2UNDO",0,"3PRINT",0
  26.         DB    "4MARK",0,"5CUT",0,"6PASTE",0,"7EXIT",0
  27.         DB    "8DEL EOL",0,"9DEL L",0,"10UDEL L",0,0
  28. PROMPT_LENGTH    =    $ - OFFSET PROMPT_STRING
  29.  
  30. VERIFY_MESS    DB    "Lose Changes (Y/N)?",0
  31. SAVE_MESS    DB    "Save as: ",0
  32. DOT_$$$        DB    ".$$$",0
  33. DOT_BAK        DB    ".BAK",0
  34. DIRTY_BITS    DB    1
  35. NORMAL        DB    07H
  36. INVERSE        DB    70H
  37. LEFT_MARGIN    DB    0
  38. MARGIN_COUNT    DB    0
  39. INSERT_MODE    DB    -1
  40. MARK_MODE    DB    0
  41. ROWS        DB    23
  42. SAVE_COLUMN    DB    0
  43. SAVE_ROW    DB    0
  44. LINE_FLAG    DB    0
  45. EVEN
  46. NAME_POINTER    DW    81H
  47. NAME_END    DW    81H
  48. STATUS_REG    DW    ?
  49. VIDEO_SEG    DW    0B000H
  50. LINE_LENGTH    DW    0
  51. UNDO_LENGTH    DW    0
  52. CUR_POSN    DW    0
  53. MARK_START    DW    0FFFFH
  54. MARK_END    DW    0
  55. MARK_HOME    DW    0
  56. TOP_OF_SCREEN    DW    0
  57. CURSOR        DW    0
  58. LAST_CHAR    DW    0
  59. COLUMNSB    LABEL    BYTE
  60. COLUMNS        DW    ?
  61. PASTE_SEG    DW    ?
  62. PASTE_SIZE    DW    0
  63. PAGE_PROC    DW    ?
  64. OLDINT24    DD    ?
  65. DISPATCH_TABLE    DW    OFFSET ABORT    ,OFFSET UNDO   ,OFFSET PRINT
  66.         DW    OFFSET MARK    ,OFFSET CUT    ,OFFSET PASTE
  67.         DW    OFFSET EXIT    ,OFFSET DEL_EOL,OFFSET DEL_L
  68.         DW    OFFSET UDEL_L  ,OFFSET BAD_KEY,OFFSET BAD_KEY
  69.         DW    OFFSET HOME    ,OFFSET UP     ,OFFSET PGUP
  70.         DW    OFFSET BAD_KEY ,OFFSET LEFT   ,OFFSET BAD_KEY
  71.         DW    OFFSET RIGHT   ,OFFSET BAD_KEY,OFFSET ENDD
  72.         DW    OFFSET DOWN    ,OFFSET PGDN   ,OFFSET INSERT
  73.         DW    OFFSET DEL_CHAR
  74.  
  75. ; The following machine instruction removes the desnow delay.  It is
  76. ; inserted into the code for EGA, VGA, and MONO displays.
  77.  
  78. NO_DESNOW = 0EBH + (OFFSET WRITE_IT - OFFSET HWAIT - 2) * 256
  79.  
  80. ;-----------------------------------------------------------------------
  81. ; We start by initialize the display, then allocate memory for the file
  82. ; and paste segments.  Parse the command line for a filename, if one was
  83. ; input, read in the file.  Finally set the INT 23 and 24 vectors.
  84. ;-----------------------------------------------------------------------
  85. BEGIN:
  86.         XOR    AX,AX
  87.         MOV    DS,AX        ;Get a zero into DS
  88.         ASSUME    DS:NOTHING
  89.         MOV    AH,12H
  90.         MOV    BL,10H        ;Get EGA info
  91.         INT    10H
  92.         CMP    BL,10H        ;Did BL change?
  93.         JE    NOT_EGA        ;If not, no EGA in system
  94.         TEST    BYTE PTR DS:[0487H],8    ;Is EGA active?
  95.         JNZ    NOT_EGA
  96.         MOV    WORD PTR CS:HWAIT,NO_DESNOW ;Get rid of desnow
  97.         MOV    AX,DS:[0484H]    ;Get number of rows
  98.         DEC    AL        ;Last row is for prompt line
  99.          MOV    CS:[ROWS],AL    ;Save the number of rows
  100. NOT_EGA:
  101.         MOV    AX,DS:[044AH]    ;Get number of columns
  102.         MOV    CS:COLUMNS,AX    ;and store it
  103.         MOV    AX,DS:[0463H]    ;Address of display card
  104.         ADD    AX,6        ;Add six to get status port
  105.         PUSH    CS
  106.         POP    DS
  107.         ASSUME    DS:CSEG
  108.         MOV    STATUS_REG,AX
  109.         CMP    AX,3BAH        ;Is this a MONO display?
  110.         JNE    COLOR        ;If not, must be a CGA
  111.         MOV    WORD PTR HWAIT,NO_DESNOW ;Get rid of desnow
  112.         JMP    SHORT MOVE_STACK
  113. COLOR:
  114.         MOV    VIDEO_SEG,0B800H;Segment for color card
  115.         XOR    BH,BH        ;Use page zero
  116.         MOV    AH,8        ;Get current attribute
  117.         INT    10H
  118.         MOV    NORMAL,AH    ;Save the normal attribute
  119.         XOR    AH,1110111B    ;Flip the color bits
  120.         MOV    INVERSE,AH
  121. MOVE_STACK:
  122.         MOV    BX,OFFSET NEW_STACK
  123.         MOV    SP,BX        ;Move the stack downward
  124.         ADD    BX,15
  125.         MOV    CL,4        ;Convert program size to
  126.         SHR    BX,CL        ; paragraphs
  127.         MOV    AH,4AH        ;Deallocate unused memory
  128.         INT    21H
  129.         MOV    BX,1000H    ;Request 64K for file segment
  130.         MOV    AH,48H
  131.         INT    21H
  132.         MOV    ES,AX
  133.         ASSUME    ES:FILE_SEG
  134.         MOV    AH,48H
  135.         INT    21H        ;Request 64K for paste buffer
  136.         JNC    GOT_ENOUGH    ;If enough memory, continue
  137. NOT_ENOUGH:
  138.         MOV    DX,OFFSET MEMORY_ERROR
  139. ERR_EXIT:
  140.         PUSH    CS
  141.         POP    DS
  142.         MOV    AH,9        ;Write the error message
  143.         INT    21H        ;DOS display service
  144.         JMP    EXIT_TO_DOS    ;Exit this program
  145. GOT_ENOUGH:
  146.         MOV    PASTE_SEG,AX    ;Use this for the paste buffer
  147. GET_FILENAME:
  148.         MOV    SI,80H        ;Point to parameters
  149.         MOV    CL,[SI]        ;Get number of characters
  150.         XOR    CH,CH        ;Make it a word
  151.         INC    SI        ;Point to first character
  152.         PUSH    SI
  153.         ADD    SI,CX        ;Point to last character
  154.         MOV    BYTE PTR [SI],0    ;Make it an ASCII string
  155.         MOV    NAME_END,SI    ;Save pointer to last character
  156.         POP    SI        ;Get back pointer to filename
  157.         CLD
  158.         JCXZ    NO_FILENAME    ;If no params, just exit
  159. DEL_SPACES:    LODSB            ;Get character into AL
  160.         CMP    AL," "        ;Is it a space?
  161.         JNE    FOUND_LETTER
  162.         LOOP    DEL_SPACES
  163. FOUND_LETTER:
  164.         DEC    SI        ;Backup pointer to first letter
  165.         MOV    NAME_POINTER,SI    ;Save pointer to filename
  166.         MOV    DX,SI
  167.         MOV    AX,3D00H    ;Setup to open file
  168.         INT    21H
  169.         JC    NO_FILENAME     ;If we can't open, must be new file
  170. FILE_OPENED:
  171.         PUSH    ES
  172.         POP    DS        ;DS has file segment also
  173.         ASSUME    DS:FILE_SEG
  174.         MOV    BX,AX        ;Get the handle into BX
  175.         XOR    DX,DX        ;Point to file buffer
  176.         MOV    AH,3FH        ;Read service
  177.         MOV    CX,0FFFEH    ;Read almost 64K bytes
  178.         INT    21H
  179.         MOV    DI,AX        ;Number of bytes read in
  180.         JNC    LOOK_FOR_EOF    ;If no error, take jump
  181.         MOV    DX,OFFSET READ_ERR_MESS
  182.         JMP    SHORT ERR_EXIT
  183. LOOK_FOR_EOF:
  184.         CMP    BYTE PTR [DI-1],1AH ;Was last char an EOF mark?
  185.         JNE    NO_EOF        ;If not, everything is OK
  186.         DEC    DI        ;Backup to last character
  187. NO_EOF:
  188.         MOV    LAST_CHAR,DI    ;Save the file size
  189.         CMP    CX,AX        ;Did the buffer fill?
  190.         MOV    DX,OFFSET FILE_TOO_BIG
  191.         JE    ERR_EXIT    ;If yes, it is too big
  192.         MOV    AH,3EH
  193.         INT    21H        ;Close the file
  194. NO_FILENAME:
  195.         PUSH    ES
  196.         PUSH    ES        ;Save file segment
  197.         MOV    AX,3524H    ;Get INT 24 vector
  198.         INT    21H
  199.         MOV    WORD PTR OLDINT24,BX  ;Store the offset
  200.         MOV    WORD PTR OLDINT24+2,ES;And the segment
  201.  
  202.         PUSH    CS
  203.         POP    DS
  204.         MOV    DX,OFFSET NEWINT24    ;Point to new vector
  205.         MOV    AX,2524H    ;Now change INT 24 vector
  206.         INT    21H    
  207.  
  208.         MOV    DX,OFFSET NEWINT23
  209.         MOV    AX,2523H    ;Set the INT 23 vector also
  210.         INT    21H
  211.  
  212.         POP    ES        ;Get back file segment
  213.         POP    DS
  214.         ASSUME    DS:FILE_SEG, ES:FILE_SEG
  215.         CALL    REDO_PROMPT    ;Draw the prompt line
  216.  
  217. ;-----------------------------------------------------------------------
  218. ; Here's the main loop.  It updates the screen, then reads a keystroke.
  219. ;-----------------------------------------------------------------------
  220. READ_A_KEY:
  221.         CMP    MARK_MODE,0    ;Is the mark state on?
  222.         JE    MARK_OFF    ;If not, skip this
  223.         OR    DIRTY_BITS,4    ;Refresh the current row
  224.         MOV    DX,CUR_POSN
  225.         CMP    SAVE_ROW,DH    ;Are we on the save row?
  226.         JE    SAME_ROW    ;If yes, then redo the row only
  227.         MOV    DIRTY_BITS,1    ;Refresh the whole screen
  228. SAME_ROW:
  229.         MOV    AX,CURSOR    ;Get cursor location
  230.         MOV    BX,MARK_HOME    ;Get the anchor mark position
  231.         CMP    AX,BX        ;Moving backward in file?
  232.         JAE    S1
  233.         MOV    MARK_START,AX    ;Switch start and end position
  234.         MOV    MARK_END,BX
  235.         JMP    SHORT MARK_OFF
  236. S1:
  237.         MOV    MARK_END,AX    ;Store start and end marks
  238.         MOV    MARK_START,BX
  239. MARK_OFF:
  240.         MOV    DX,CUR_POSN
  241.         MOV    SAVE_ROW,DH
  242.         CALL    SET_CURSOR    ;Position the cursor
  243.         TEST    DIRTY_BITS,1    ;Look at screen dirty bit
  244.         JZ    SCREEN_OK    ;If zero, screen is OK
  245.  
  246.         MOV    AH,1        ;Get keyboard status
  247.         INT    16H        ;Any keys ready?
  248.         JNZ    CURRENT_OK    ;If yes, skip the update
  249.         CALL    DISPLAY_SCREEN    ;Redraw the screen
  250.         MOV    DIRTY_BITS,0    ;Mark screen as OK
  251. SCREEN_OK:
  252.         TEST    DIRTY_BITS,4    ;Is the current line dirty?
  253.         JZ    CURRENT_OK    ;If not, take jump
  254.         CALL    DISPLAY_CURRENT    ;Redraw the current line
  255.         MOV    DIRTY_BITS,0    ;Mark screen as OK
  256. CURRENT_OK:
  257.         XOR    AH,AH        ;Read the next key
  258.         INT    16H
  259.         OR    AL,AL        ;Is this an extended code?
  260.         JZ    EXTENDED_CODE
  261.         CMP    AH,0EH        ;Was it the backspace key?
  262.         JE    BACK_SPACE
  263.         CALL    INSERT_KEY    ;Put this character in the file
  264.         JMP    READ_A_KEY    ;Get another key
  265. BACK_SPACE:
  266.         CMP    CURSOR,0    ;At start of file?
  267.         JE    BAD_KEY        ;If at start, can't backspace
  268.         CALL    LEFT        ;Move left one space
  269.         CALL    DEL_CHAR    ;And delete the character
  270.         JMP    READ_A_KEY
  271. EXTENDED_CODE:
  272.         CMP    AH,84H        ;Is it control PgUp?
  273.         JNE    NOT_TOP
  274.         CALL    TOP
  275.         JMP    READ_A_KEY
  276. NOT_TOP:
  277.         CMP    AH,76H        ;Is it control PgDn?
  278.         JNE    NOT_BOTTOM
  279.         CALL    BOTTOM
  280. BAD_KEY:
  281.         JMP    READ_A_KEY
  282. NOT_BOTTOM:
  283.         CMP    AH,73H        ;Is it control left arrow?
  284.         JE    SH_LEFT
  285.         CMP    AH,74H        ;Is it control right arrow?
  286.         JE    SH_RIGHT
  287.         CMP    AH,53H        ;Skip high numbered keys
  288.         JA    BAD_KEY
  289.         XCHG    AH,AL
  290.         SUB    AL,3BH        ;Also skip low numbered keys
  291.         JC    BAD_KEY
  292.         SHL    AX,1        ;Make the code an offset
  293.         MOV    BX,AX        ;Put offset in BX
  294.         CALL    CS:DISPATCH_TABLE[BX] ;Call the key procedure
  295.         JMP    READ_A_KEY    ;Then read another key
  296.  
  297. ;-----------------------------------------------------------------------
  298. ; These two routines shift the display right or left to allow editing
  299. ; files which contain lines longer than 80 columns.
  300. ;-----------------------------------------------------------------------
  301. SH_RIGHT    PROC    NEAR
  302.         CMP    LEFT_MARGIN,255 - 8 ;Past max allowable margin?
  303.         JAE    NO_SHIFT    ;Then can't move any more
  304.         ADD    LEFT_MARGIN,8    ;This moves the margin over
  305. SH_RETURN:
  306.         CALL    CURSOR_COL    ;Compute column for cursor
  307.         MOV    DX,CUR_POSN
  308.         MOV    SAVE_COLUMN,DL    ;Save the current column
  309.         MOV    DIRTY_BITS,1    ;Redraw the screen
  310. NO_SHIFT:
  311.         JMP    READ_A_KEY
  312. SH_RIGHT    ENDP
  313.  
  314. SH_LEFT        PROC    NEAR
  315.         CMP    LEFT_MARGIN,0    ;At start of line already?
  316.         JE    NO_SHIFT    ;If yes, then don't shift
  317.         SUB    LEFT_MARGIN,8    ;Move the window over
  318.         JMP    SH_RETURN
  319. SH_LEFT        ENDP
  320.  
  321. ;-----------------------------------------------------------------------
  322. ; This moves the cursor to the top of the file.
  323. ;-----------------------------------------------------------------------
  324. TOP        PROC    NEAR
  325.         XOR    AX,AX        ;Get a zero into AX
  326.         MOV    CURSOR,AX    ;Cursor to start of file
  327.         MOV    TOP_OF_SCREEN,AX
  328.         MOV    LEFT_MARGIN,AL    ;Move to far left margin
  329.         MOV    DIRTY_BITS,1    ;Redraw the screen
  330.         MOV    CUR_POSN,AX    ;Home the cursor
  331.         MOV    SAVE_COLUMN,AL    ;Save the cursor column
  332.         RET
  333. TOP        ENDP
  334.  
  335. ;-----------------------------------------------------------------------
  336. ; This moves the cursor to the bottom of the file
  337. ;-----------------------------------------------------------------------
  338. BOTTOM        PROC    NEAR
  339.         MOV    DH,ROWS        ;Get screen size
  340.         MOV    SI,LAST_CHAR    ;Point to last character
  341.         MOV    LEFT_MARGIN,0    ;Set window to start of line
  342.         CALL    LOCATE        ;Adjust the screen position
  343.         CALL    HOME        ;Move cursor to start of line
  344.         MOV    DIRTY_BITS,1    ;This will redraw the screen
  345.         RET
  346. BOTTOM        ENDP
  347.  
  348. ;-----------------------------------------------------------------------
  349. ; This deletes from the cursor position to the end of line.
  350. ;-----------------------------------------------------------------------
  351. DEL_EOL        PROC    NEAR
  352.         MOV    LINE_FLAG,0
  353.         PUSH    CURSOR        ;Save starting cursor location
  354.         CALL    ENDD        ;Move the the end of line
  355.         POP    SI        ;Get back starting cursor
  356.         MOV    CX,CURSOR    ;Offset of the end of line
  357.         MOV    CURSOR,SI    ;Restore starting cursor
  358.         JMP    DEL_END        ;Delete characters to end
  359. DEL_EOL        ENDP
  360.  
  361. ;-----------------------------------------------------------------------
  362. ; This deletes a line, placing it in the line buffer.
  363. ;-----------------------------------------------------------------------
  364. DEL_L        PROC    NEAR
  365.         MOV    LINE_FLAG,1
  366.         CALL    FIND_START    ;Find start of this line
  367.         MOV    CURSOR,SI    ;This will be the new cursor
  368.         PUSH    SI        ;Save the cursor position
  369.         CALL    FIND_NEXT    ;Find the next line
  370.         MOV    CX,SI        ;CX will hold line length
  371.         POP    SI        ;Get back new cursor location
  372. DEL_END:
  373.         SUB    CX,SI        ;Number of bytes on line
  374.         OR    CH,CH        ;Is line too long to fit
  375.         JZ    NOT_TOO_LONG
  376.         MOV    CX,100H        ;Only save 256 characters
  377. NOT_TOO_LONG:
  378.         MOV    LINE_LENGTH,CX    ;Store length of deleted line
  379.         JCXZ    NO_DEL_L
  380.         MOV    DI,OFFSET LINE_BUFFER ;Buffer for deleted line
  381.  
  382.         PUSH    CX
  383.         PUSH    ES
  384.         PUSH    CS
  385.         POP    ES        ;Line buffer is in CSEG
  386.         REP    MOVSB        ;Put deleted line in buffer
  387.         POP    ES        ;Get back file segment
  388.         POP    AX
  389.  
  390.         MOV    CX,LAST_CHAR    ;Get the file size
  391.         SUB    LAST_CHAR,AX    ;Subtract the deleted line
  392.         MOV    SI,CURSOR    ;Get new cursor location
  393.         MOV    DI,SI
  394.         ADD    SI,AX        ;SI points to end of file
  395.         SUB    CX,SI        ;Length of remaining file
  396.         JCXZ    NO_DEL_L
  397.         REP    MOVSB        ;Shift remainder of file up
  398. NO_DEL_L:
  399.         MOV    DX,CUR_POSN    ;Get cursor row/column
  400.         MOV    SI,CURSOR    ;Get cursor offset
  401.         CALL    LOCATE        ;Adjust the screen position
  402.         MOV    DIRTY_BITS,1    ;Redraw the screen
  403.         RET
  404. DEL_L        ENDP
  405.  
  406. ;-----------------------------------------------------------------------
  407. ; This undeletes a line by copying it from the line buffer into the file
  408. ;-----------------------------------------------------------------------
  409. UDEL_L        PROC    NEAR
  410.         CMP    LINE_FLAG,0    ;Is this an end of line only?
  411.         JE    UDEL_EOL    ;If yes, don't home the cursor
  412.         CALL    HOME        ;Move cursor to home
  413. UDEL_EOL:
  414.         MOV    AX,LINE_LENGTH    ;Length of deleted line
  415.         MOV    SI,OFFSET LINE_BUFFER
  416.         JMP    INSERT_STRING
  417. UDEL_L        ENDP
  418.  
  419. ;-----------------------------------------------------------------------
  420. ; These routines move the cursor left and right.
  421. ;-----------------------------------------------------------------------
  422. LEFT        PROC    NEAR
  423.         CMP    CURSOR,0    ;At start of file?
  424.         JZ    LR_NO_CHANGE    ;Then can't move left
  425.         MOV    DX,CUR_POSN
  426.         OR    DL,DL        ;At first column?
  427.         JZ    MOVE_UP        ;If yes, then move up one
  428.         DEC    CURSOR        ;Shift the cursor offset
  429. LR_RETURN:
  430.         CALL    CURSOR_COL    ;Compute column for cursor
  431.         MOV    SAVE_COLUMN,DL    ;Save the cursor column
  432. LR_NO_CHANGE:
  433.         MOV    UNDO_LENGTH,0
  434.         RET
  435. MOVE_UP:
  436.         CALL    UP        ;Move up to next row
  437.         JMP    SHORT ENDD    ;And move to end of line
  438. LEFT        ENDP
  439.  
  440. RIGHT        PROC    NEAR
  441.         MOV    SI,CURSOR
  442.         CMP    SI,LAST_CHAR    ;At end of file?
  443.         JE    LR_NO_CHANGE    ;If yes, then can't move
  444.         CMP    BYTE PTR [SI],CR;At end of line?
  445.         JE    MOVE_DOWN    ;If yes, then move down
  446.         INC    CURSOR        ;Advance the cursor
  447.         JMP    LR_RETURN
  448. MOVE_DOWN:
  449.         CALL    HOME        ;Move to start of line
  450.         JMP    DOWN        ;And move down one row
  451. RIGHT        ENDP
  452.  
  453. ;-----------------------------------------------------------------------
  454. ; This moves the cursor to the start of the current line.
  455. ;-----------------------------------------------------------------------
  456. HOME        PROC    NEAR
  457.         CALL    FIND_START    ;Find start of line
  458.         MOV    CURSOR,SI    ;Save the new cursor
  459.         MOV    SAVE_COLUMN,0    ;Save the cursor column
  460.         MOV    BYTE PTR CUR_POSN,0 ;Store column number
  461.         RET
  462. HOME        ENDP
  463.  
  464. ;-----------------------------------------------------------------------
  465. ; This moves the cursor to the end of the current line
  466. ;-----------------------------------------------------------------------
  467. ENDD        PROC    NEAR
  468.         MOV    SI,CURSOR
  469.         CALL    FIND_EOL    ;Find end of this line
  470.         MOV    CURSOR,SI    ;Store the new cursor
  471.         CALL    CURSOR_COL    ;Compute the correct column
  472.         MOV    SAVE_COLUMN,DL    ;Save the cursor column
  473.         RET
  474. ENDD        ENDP
  475.  
  476. ;-----------------------------------------------------------------------
  477. ; This moves the cursor up one row.  If the cursor is at the first row,
  478. ; the screen is scrolled down.
  479. ;-----------------------------------------------------------------------
  480. UP        PROC    NEAR
  481.         MOV    UNDO_LENGTH,0
  482.         MOV    DX,CUR_POSN
  483.         MOV    SI,CURSOR
  484.         OR    DH,DH        ;At top row already?
  485.         JZ    SCREEN_DN    ;If yes, then scroll down
  486.         DEC    DH        ;Move cursor up one row
  487.         CALL    FIND_CR        ;Find the beginning of this row
  488.         MOV    CURSOR,SI
  489.         CALL    FIND_START    ;Find start of this row
  490.         MOV    CURSOR,SI
  491.         CALL    SHIFT_RIGHT    ;Skip over to current column
  492. AT_TOP:
  493.         RET
  494. SCREEN_DN:
  495.         MOV    SI,TOP_OF_SCREEN
  496.         OR    SI,SI        ;At start of file?
  497.         JZ    AT_TOP        ;If at top, then do nothing
  498.         CALL    FIND_PREVIOUS    ;Find the preceeding line
  499.         MOV    TOP_OF_SCREEN,SI;Save new top of screen
  500.         MOV    SI,CURSOR
  501.         CALL    FIND_PREVIOUS    ;Find the preceeding line
  502.         MOV    CURSOR,SI    ;This is the new cursor
  503. SHIFT_RET:
  504.         MOV    DIRTY_BITS,1    ;Need to redraw screen
  505.         MOV    SI,CURSOR
  506.         MOV    DX,CUR_POSN
  507.         JMP    SHIFT_RIGHT    ;Move cursor to current column
  508. UP        ENDP
  509.  
  510. ;-----------------------------------------------------------------------
  511. ; This moves the cursor down one row.  When the last row is reached,
  512. ; the screen is shifted up one row.
  513. ;-----------------------------------------------------------------------
  514. DOWN        PROC    NEAR
  515.         MOV    UNDO_LENGTH,0
  516.         MOV    DX,CUR_POSN
  517.         CMP    DH,ROWS        ;At bottom row already?
  518.         MOV    SI,CURSOR    ;Get position in file
  519.         JE    SCREEN_UP    ;If at bottom, then scroll up
  520.         CALL    FIND_NEXT    ;Find the start of next line
  521.         JC    DOWN_RET    ;If no more lines, then return
  522.         MOV    CURSOR,SI
  523.         INC    DH        ;Advance cursor to next row
  524.         CALL    SHIFT_RIGHT    ;Move cursor to current column
  525. DOWN_RET:
  526.         RET
  527. SCREEN_UP:
  528.         CMP    SI,LAST_CHAR    ;Get cursor offset
  529.         JE    DOWN_RET
  530.         CALL    FIND_START    ;Find the start of this line
  531.         MOV    CURSOR,SI    ;This is the new cursor
  532.         CALL    FIND_NEXT    ;Find the offset of next line
  533.         JC    SHIFT_RET    ;If no more lines then return
  534.         MOV    CURSOR,SI    ;This is the new cursor
  535.         MOV    SI,TOP_OF_SCREEN;Get the start of the top row
  536.         CALL    FIND_NEXT    ;And find the next line
  537.         MOV    TOP_OF_SCREEN,SI;Store the new top of screen
  538.         JMP    SHIFT_RET
  539. DOWN        ENDP
  540.  
  541. ;-----------------------------------------------------------------------
  542. ; These two routines move the screen one page at a time by calling the
  543. ; UP and DOWN procedures.
  544. ;-----------------------------------------------------------------------
  545. PGDN        PROC    NEAR
  546.         MOV    PAGE_PROC,OFFSET DOWN
  547. PAGE_UP_DN:
  548.         MOV    CL,ROWS        ;Get length of the screen
  549.         SUB    CL,5        ;Don't page a full screen
  550.         XOR    CH,CH        ;Make it a word
  551. PAGE_LOOP:
  552.         PUSH    CX
  553.         CALL    PAGE_PROC    ;Move the cursor down
  554.         POP    CX
  555.         LOOP    PAGE_LOOP    ;Loop for one page length
  556.         RET
  557. PGDN        ENDP
  558.  
  559. PGUP        PROC    NEAR
  560.         MOV    PAGE_PROC,OFFSET UP
  561.         JMP    PAGE_UP_DN
  562. PGUP        ENDP
  563.  
  564. ;-----------------------------------------------------------------------
  565. ; This toggles the insert/overstrike mode.
  566. ;-----------------------------------------------------------------------
  567. INSERT        PROC    NEAR
  568.         NOT    INSERT_MODE    ;Toggle the switch
  569.         JMP    REDO_PROMPT    ;Redraw the insert status
  570. INSERT        ENDP
  571.  
  572. ;-----------------------------------------------------------------------
  573. ; This deletes the character at the cursor by shifting the remaining 
  574. ; characters forward.
  575. ;-----------------------------------------------------------------------
  576. DEL_CHAR    PROC    NEAR
  577.         MOV    CX,LAST_CHAR
  578.         MOV    SI,CURSOR
  579.         MOV    DI,SI
  580.         CMP    SI,CX        ;Are we at end of file?
  581.         JAE    NO_DEL        ;If yes, then don't delete
  582.         LODSB
  583.         CALL    SAVE_CHAR    ;Save it for UNDO function
  584.         MOV    AH,[SI]        ;Look at the next character also
  585.         PUSH    AX        ;Save character were deleting
  586.         DEC    LAST_CHAR    ;Shorten the file by one
  587.         SUB    CX,SI
  588.         REP    MOVSB        ;Move file down one notch
  589.  
  590.         POP    AX        ;Get back character we deleted
  591.         CMP    AL,CR        ;Did we delete a CR?
  592.         JE    COMBINE
  593.         OR    DIRTY_BITS,4    ;Current line is dirty
  594. NO_DEL:
  595.         RET
  596. COMBINE:
  597.         CMP    AH,LF        ;Was the next character a LF?
  598.         JNE    NO_DEL_LF
  599.         CALL    DEL_CHAR    ;Now delete the line feed
  600. NO_DEL_LF:
  601.         CALL    DISPLAY_BOTTOM    ;Repaint bottom of the screen
  602.         MOV    DX,CUR_POSN
  603.         MOV    SAVE_COLUMN,DL    ;Save the cursor column
  604.         RET
  605. DEL_CHAR    ENDP
  606.  
  607. ;-----------------------------------------------------------------------
  608. ; This toggles the mark state and resets the paste buffer pointers.
  609. ;-----------------------------------------------------------------------
  610. MARK        PROC    NEAR
  611.         XOR    AX,AX
  612.         NOT    MARK_MODE    ;Toggle the mode flag
  613.         CMP    MARK_MODE,AL    ;Turning mode ON?
  614.         JNE    MARK_ON
  615.         MOV    DIRTY_BITS,1    ;Need to redraw the screen
  616.         MOV    MARK_START,0FFFFH
  617.         JMP    SHORT MARK_RET
  618. MARK_ON:
  619.         MOV    AX,CURSOR    ;Get the cursor offset
  620.         MOV    MARK_START,AX    ;Start of marked range
  621. MARK_RET:
  622.         MOV    MARK_END,  AX    ;End of marked range
  623.         MOV    MARK_HOME, AX    ;Center of marked range
  624.         RET
  625. MARK        ENDP
  626.  
  627. ;-----------------------------------------------------------------------
  628. ; This removes the marked text and places it in the paste buffer
  629. ;-----------------------------------------------------------------------
  630. CUT        PROC    NEAR
  631.         CMP    MARK_MODE,0    ;Is the mark mode on?
  632.         JE    NO_MARK        ;If not, then do nothing
  633.         MOV    CX,MARK_END    ;Get end of mark region
  634.         MOV    SI,MARK_START    ;Get start of mark region
  635.         SUB    CX,SI        ;Number of bytes selected
  636.         MOV    PASTE_SIZE,CX
  637.         JCXZ    NO_MARK
  638.         XOR    DI,DI        ;Point to paste bufferf
  639.  
  640.         PUSH    CX
  641.         PUSH    ES
  642.         MOV    ES,PASTE_SEG    ;Get the paste segment
  643.         REP    MOVSB        ;Put deleted text in buffer
  644.         POP    ES
  645.         POP    AX
  646.  
  647.         MOV    CX,LAST_CHAR
  648.         SUB    LAST_CHAR,AX    ;Shorten the file this much
  649.         MOV    DI,MARK_START
  650.         MOV    SI,MARK_END
  651.         SUB    CX,SI
  652.         JCXZ    NO_DELETE
  653.         REP    MOVSB        ;Shorten the file
  654. NO_DELETE:
  655.         MOV    DX,CUR_POSN
  656.         MOV    SI,MARK_START
  657.         CALL    LOCATE        ;Adjust the screen position
  658.         CALL    MARK        ;This turns off select
  659. NO_MARK:
  660.         RET
  661. CUT        ENDP
  662.  
  663. ;-----------------------------------------------------------------------
  664. ; This copies the paste buffer into the file at the cursor location
  665. ;-----------------------------------------------------------------------
  666. PASTE        PROC    NEAR
  667.         MOV    AX,PASTE_SIZE    ;Number of characters in buffer
  668.         OR    AX,AX        ;Any there?
  669.         JZ    NO_PASTE    ;If not, nothing to paste
  670.         MOV    SI,CURSOR    ;Get cursor location
  671.         PUSH    AX
  672.         PUSH    SI
  673.         CALL    OPEN_SPACE    ;Make room for new characters
  674.         POP    DI
  675.         POP    CX
  676.         JC    NO_PASTE    ;If no room, just exit
  677.         XOR    SI,SI        ;Point to paste buffer
  678.         PUSH    DS
  679.         MOV    DS,PASTE_SEG    ;Segment of paste buffer
  680.         REP    MOVSB        ;Copy in the new characters
  681.         POP    DS
  682.         MOV    SI,DI
  683.         MOV    CURSOR,SI    ;Cursor moved to end of insert
  684.         MOV    DX,CUR_POSN    ;Get current cursor row
  685.         CALL    LOCATE        ;Adjust the screen position
  686.         MOV    DIRTY_BITS,1    ;Redraw the screen
  687. NO_PASTE:
  688.         RET
  689. PASTE        ENDP
  690.  
  691. ;-----------------------------------------------------------------------
  692. ; This prints the marked text.  If printer fails, it is canceled.
  693. ;-----------------------------------------------------------------------
  694. PRINT        PROC    NEAR
  695.         CMP    MARK_MODE,0    ;Is mark mode on?
  696.         JE    PRINT_RET    ;If not, nothing to print
  697.         MOV    CX,MARK_END    ;End of marked region
  698.         MOV    SI,MARK_START    ;Start of marked region
  699.         SUB    CX,SI        ;Number of bytes selected
  700.         JCXZ    PRINT_DONE    ;If nothing to print, return
  701.  
  702.         MOV    AH,2
  703.         XOR    DX,DX        ;Select printer 0
  704.         INT    17H        ;Get printer status
  705.         TEST    AH,10000000B    ;Is busy bit set?
  706.         JZ    PRINT_DONE
  707.         TEST    AH,00100000B    ;Is printer out of paper?
  708.         JNZ    PRINT_DONE
  709. PRINT_LOOP:
  710.         LODSB
  711.         XOR    AH,AH
  712.         INT    17H        ;Print the character
  713.         ROR    AH,1        ;Check time out bit
  714.         JC    PRINT_DONE    ;If set, quit printing
  715.         LOOP    PRINT_LOOP
  716.         MOV    AL,CR
  717.         XOR    AH,0
  718.         INT    17H        ;Finish with a CR
  719. PRINT_DONE:
  720.         CALL    MARK        ;Turn off the mark state
  721. PRINT_RET:
  722.         RET
  723. PRINT        ENDP
  724.  
  725. ;-----------------------------------------------------------------------
  726. ; This command restores any characters which have recently been deleted.
  727. ;-----------------------------------------------------------------------
  728. UNDO        PROC    NEAR
  729.         XOR    AX,AX
  730.         XCHG    AX,UNDO_LENGTH    ;Get buffer length
  731.         MOV    SI,OFFSET UNDO_BUFFER
  732.         JMP    INSERT_STRING
  733. UNDO        ENDP
  734.  
  735. ;-----------------------------------------------------------------------
  736. ; This inserts AX characters from CS:SI into the file.
  737. ;-----------------------------------------------------------------------
  738. INSERT_STRING    PROC    NEAR
  739.         PUSH    SI        ;Save string buffer
  740.         MOV    SI,CURSOR    ;Get cursor offset
  741.         PUSH    AX        ;Save length of string
  742.         PUSH    SI
  743.         CALL    OPEN_SPACE    ;Make space to insert string
  744.         POP    DI        ;Get back cursor position
  745.         POP    CX        ;Get back string length
  746.         POP    SI        ;Get back string buffer
  747.         JC    NO_SPACE    ;If no space available, exit
  748.  
  749.         PUSH    DS
  750.         PUSH    CS
  751.         POP    DS
  752.         ASSUME    DS:CSEG
  753.         REP    MOVSB        ;Copy the characters in
  754.         MOV    SI,CURSOR    ;Get the new cursor offset
  755.         MOV    DX,CUR_POSN    ;Also get the current row
  756.         MOV    DIRTY_BITS,1    ;And redraw the screen
  757.         POP    DS
  758.         ASSUME    DS:NOTHING
  759.         CALL    LOCATE        ;Adjust the screen position
  760. NO_SPACE:
  761.         RET
  762. INSERT_STRING    ENDP
  763.  
  764. ;-----------------------------------------------------------------------
  765. ; This adds a character to the undo buffer.
  766. ;-----------------------------------------------------------------------
  767. SAVE_CHAR    PROC    NEAR
  768.         MOV    BX,UNDO_LENGTH
  769.         OR    BH,BH        ;Is buffer filled?
  770.         JNZ    NO_SAVE
  771.         INC    UNDO_LENGTH
  772.         MOV    BYTE PTR CS:UNDO_BUFFER[BX],AL
  773. NO_SAVE:
  774.         RET
  775. SAVE_CHAR    ENDP
  776.  
  777. ;-----------------------------------------------------------------------
  778. ; This prompts for a verify keystroke then exits without saving the file
  779. ;-----------------------------------------------------------------------
  780. ABORT        PROC    NEAR
  781.         ASSUME    DS:CSEG
  782.         PUSH    CS
  783.         POP    DS
  784.         MOV    DH,ROWS        ;Last row on display
  785.         INC    DH        ;Bottom row of screen
  786.         XOR    DL,DL        ;First column
  787.         MOV    SI,OFFSET VERIFY_MESS
  788.         CALL    TTY_STRING    ;Display verify message
  789.  
  790.         XOR    AH,AH        ;Read the next key
  791.         INT    16H        ;BIOS read key routine
  792.         OR    AL,32        ;Convert to lower case
  793.         CMP    AL,"y"        ;Was answer Yes?
  794.         JE    FINISHED    ;If yes, then were finished
  795.         CALL    REDO_PROMPT    ;If not, redraw the prompt
  796.         PUSH    ES
  797.         POP    DS        ;Set DS back to file segment
  798.         RET
  799. FINISHED:
  800.         MOV    DH,ROWS        ;Move to last row on screen
  801.         XOR    DL,DL        ;And column zero
  802.         CALL    SET_CURSOR
  803.         INC    DH
  804.         CALL    ERASE_EOL    ;Erase the last row
  805. EXIT_TO_DOS:
  806.         PUSH    CS
  807.         POP    DS        ;Point to code segment
  808.         MOV    DX,OFFSET COPYRIGHT
  809.         MOV    AH,9        ;Display string
  810.         INT    21H
  811.         MOV    AX,4C00H
  812.         INT    21H
  813.  
  814. ABORT        ENDP
  815.  
  816. ;-----------------------------------------------------------------------
  817. ; This prompts for a filename then writes the file.  The original file
  818. ; is renamed to filename.BAK.  If an invalid filename is entered, the 
  819. ; speaker is beeped.
  820. ;-----------------------------------------------------------------------
  821. EXIT        PROC    NEAR
  822.  
  823.         PUSH    DS
  824.         PUSH    ES
  825.         MOV    AX,CS
  826.         MOV    DS,AX
  827.         MOV    ES,AX
  828.         ASSUME    DS:CSEG, ES:CSEG
  829. NEXT_LETTER:
  830.         MOV    DH,ROWS
  831.         INC    DH        ;Last row on the screen
  832.         XOR    DL,DL        ;First column
  833.         MOV    SI,OFFSET SAVE_MESS
  834.         PUSH    DX
  835.         CALL    TTY_STRING    ;Display a prompt
  836.         POP    DX
  837.         ADD    DL,9        ;Move right 9 spaces
  838.         MOV    SI,NAME_POINTER
  839.         CALL    TTY_STRING    ;Display the filename
  840.  
  841.         XOR    AH,AH        ;Read the next key
  842.         INT    16H
  843.         MOV    DI,NAME_END    ;This points to last letter
  844.         OR    AL,AL        ;Is it a real character?
  845.         JZ    NEXT_LETTER    ;Ignore special keys
  846.         CMP    AL,27        ;Is it escape?
  847.         JNE    NOT_ESCAPE
  848.  
  849.         MOV    DIRTY_BITS,1    ;Redraw the screen
  850.         POP    ES        ;Get back file segments
  851.         POP    DS
  852.         JMP    REDO_PROMPT    ;Redraw the prompt
  853. NOT_ESCAPE:
  854.         CMP    AL,13        ;Is it CR?
  855.         JE    GOT_NAME
  856.         CMP    AL,8        ;Is it a backspace?
  857.         JNE    NORMAL_LETTER
  858.         CMP    DI,NAME_POINTER    ;At first letter?
  859.         JLE    NEXT_LETTER    ;If yes, dont erase it
  860.         MOV    BYTE PTR [DI-1],0
  861.         DEC    NAME_END
  862.         JMP    NEXT_LETTER
  863. NORMAL_LETTER:
  864.         CMP    DI,81H + 65    ;Too many letters?
  865.         JG    NEXT_LETTER    ;If yes, ignore them
  866.         XOR    AH,AH
  867.         STOSW            ;Store the new letter
  868.         INC    NAME_END    ;Name is one character longer
  869.         JMP    NEXT_LETTER    ;Read another keystroke
  870. GOT_NAME:
  871.         MOV    DX,NAME_POINTER    ;Point to the filename
  872.         MOV    AX,4300H    ;Get the files attribute
  873.         INT    21H
  874.         JNC    NAME_OK        ;If no error, filename is OK
  875.         CMP    AX,3        ;Was it path not found error?
  876.         JE    BAD_NAME    ;If yes, filename was bad
  877. NAME_OK:
  878.         MOV    SI,OFFSET DOT_$$$    ;Point to the ".$$$"
  879.         MOV    DI,OFFSET NAME_DOT_$$$
  880.         CALL    CHG_EXTENSION        ;Add the new extension
  881.  
  882.         MOV    DX,OFFSET NAME_DOT_$$$    ;Point to the temp filename
  883.         MOV    AH,3CH            ;Function to create file
  884.         MOV    CX,0020H        ;Attribute for new file
  885.         INT    21H            ;Try to create the file
  886.         JNC    NAME_WAS_OK        ;Continue if name was OK
  887. BAD_NAME:
  888.         MOV    AX,0E07H    ;Write a bell character
  889.         INT    10H        ;BIOS tty service
  890.         JMP    NEXT_LETTER    ;Get another letter
  891. WRITE_ERROR:
  892.         MOV    AH,3EH        ;Close the file
  893.         INT    21H
  894.         JMP    BAD_NAME    ;Filename must be bad
  895. NAME_WAS_OK:
  896.         XOR    DX,DX        ;This is the file buffer
  897.         MOV    CX,LAST_CHAR    ;Number of chars in file
  898.         MOV    DI,CX
  899.         MOV    BX,AX        ;This is the handle
  900.         MOV    AH,40H        ;Write to the file
  901.         POP    DS        ;Recover buffer segment
  902.         CMP    CX,0FFFFH    ;Is buffer already full?
  903.         JE    DONT_ADD_EOF    ;If yes, dont add EOF mark
  904.         INC    CX        ;Plus one character for EOF mark
  905.         MOV    BYTE PTR [DI],1AH;Add the EOF marker
  906. DONT_ADD_EOF:
  907.         INT    21H        ;Write the buffer contents
  908.         POP    DS
  909.         JC    WRITE_ERROR    ;Exit on a write error
  910.         CMP    AX,CX        ;Was entire file written?
  911.         JNE    WRITE_ERROR    ;If not, exit
  912.  
  913.         PUSH    CS
  914.         POP    DS        ;Get the code segment
  915.         MOV    AH,3EH
  916.         INT    21H            ;Close the temp file
  917.         MOV    SI,OFFSET DOT_BAK    ;Point to the ".BAK"
  918.         MOV    DI,OFFSET NAME_DOT_BAK
  919.         CALL    CHG_EXTENSION        ;Make the backup filename
  920.  
  921.         MOV    DX,OFFSET NAME_DOT_BAK    ;Point to the backup name
  922.         MOV    AH,41H
  923.         INT    21H            ;Delete existing backup file
  924.         MOV    DI,OFFSET NAME_DOT_BAK
  925.         MOV    DX,NAME_POINTER
  926.         MOV    AH,56H
  927.         INT    21H
  928.  
  929.         MOV    DI,NAME_POINTER    ;Point to new filename
  930.         MOV    DX,OFFSET NAME_DOT_$$$ ;Point to temporary file
  931.         MOV    AH,56H        ;Rename temp to new file
  932.         INT    21H        ;DOS function to rename
  933.         POP    AX        ;Restore the stack
  934.         POP    AX
  935.         JMP    FINISHED
  936. EXIT        ENDP
  937.  
  938. ;-----------------------------------------------------------------------
  939. ; This subroutine displays a character by writing directly
  940. ; to the screen buffer.  To avoid screen noise (snow) on the color
  941. ; card, the horizontal retrace has to be monitored.
  942. ;-----------------------------------------------------------------------
  943. WRITE_INVERSE    PROC    NEAR
  944.         ASSUME    DS:FILE_SEG, ES:FILE_SEG
  945.         MOV    BH,INVERSE    ;Attribute for inverse video
  946.         JMP    SHORT WRITE_SCREEN
  947. WRITE_NORMAL:
  948.         MOV    BH,NORMAL    ;Attribute for normal video
  949. WRITE_SCREEN:
  950.         MOV    BL,AL        ;Save the character
  951.         PUSH    ES
  952.         MOV    DX,STATUS_REG     ;Retrieve status register
  953.         MOV    ES,VIDEO_SEG    ;Get segment of video buffer
  954. HWAIT:
  955.         IN    AL,DX        ;Get video status
  956.         ROR    AL,1        ;Look at horizontal retrace
  957.         JNC    HWAIT        ;Wait for retrace
  958. WRITE_IT:
  959.         MOV    AX,BX        ;Get the character/attribute
  960.         STOSW            ;Write the character
  961.         POP    ES
  962.         RET
  963. WRITE_INVERSE    ENDP
  964.  
  965. ;-----------------------------------------------------------------------
  966. ; This moves the cursor to the row/column in DX.
  967. ;-----------------------------------------------------------------------
  968. SET_CURSOR    PROC    NEAR
  969.         XOR    BH,BH        ;Were using page zero
  970.         MOV    AH,2        ;BIOS set cursor function
  971.         INT    10H
  972.         RET
  973. SET_CURSOR    ENDP
  974.  
  975. ;-----------------------------------------------------------------------
  976. ; This computes the video buffer offset for the row/column in DX
  977. ;----------------------------------------------------------------------
  978. POSITION    PROC    NEAR
  979.         MOV    AX,COLUMNS    ;Take columns per row
  980.         MUL    DH        ;Times row number
  981.         XOR    DH,DH
  982.         ADD    AX,DX        ;Add in the column number
  983.         SHL    AX,1        ;Times 2 for offset
  984.         MOV    DI,AX        ;Return result in DI
  985.         RET
  986. POSITION    ENDP
  987.  
  988. ;-----------------------------------------------------------------------
  989. ; This erases from the location in DX to the right edge of the screen
  990. ;-----------------------------------------------------------------------
  991. ERASE_EOL    PROC    NEAR
  992.         CALL    POSITION    ;Find screen offset
  993.         MOV    CX,COLUMNS    ;Get screen size
  994.         SUB    CL,DL        ;Subtract current position
  995.         JCXZ    NO_CLEAR
  996. ERASE_LOOP:
  997.         MOV    AL," "        ;Write blanks to erase
  998.         CALL    WRITE_NORMAL    ;Display it
  999.         LOOP    ERASE_LOOP
  1000. NO_CLEAR:    RET
  1001. ERASE_EOL    ENDP
  1002.  
  1003. ;-----------------------------------------------------------------------
  1004. ; This displays the function key prompt and insert mode state
  1005. ;-----------------------------------------------------------------------
  1006. REDO_PROMPT    PROC    NEAR
  1007.         ASSUME    DS:NOTHING, ES:NOTHING
  1008.         PUSH    DS
  1009.         PUSH    CS
  1010.         POP    DS
  1011.         ASSUME    DS:CSEG
  1012.         MOV    DH,ROWS        ;Put prompt at last row
  1013.         INC    DH
  1014.         XOR    DL,DL        ;And column 0
  1015.         CALL    POSITION    ;Convert to screen offset
  1016.         MOV    SI,OFFSET PROMPT_STRING
  1017. KEY_LOOP:
  1018.         MOV    AL,"F"        ;Display an "F"
  1019.         CALL    WRITE_NORMAL
  1020.         LODSB
  1021.         OR    AL,AL        ;Last key in prompt?
  1022.         JZ    PROMPT_DONE
  1023.         CALL    WRITE_NORMAL
  1024.  
  1025.         CMP    BYTE PTR CS:[SI],"0"    ;Is it F10?
  1026.         JNE    TEXT_LOOP
  1027.         LODSB
  1028.         CALL    WRITE_NORMAL
  1029. TEXT_LOOP:
  1030.         LODSB
  1031.         OR    AL,AL        ;Last letter in word?
  1032.         JNZ    WRITE_CHAR
  1033.  
  1034.         MOV    AL," "        ;Display a space
  1035.         CALL    WRITE_NORMAL
  1036.         JMP    KEY_LOOP
  1037. WRITE_CHAR:
  1038.         CALL    WRITE_INVERSE    ;Display the letter
  1039.         JMP    TEXT_LOOP    ;Do the next letter
  1040. PROMPT_DONE:
  1041.         MOV    DH,ROWS
  1042.         INC    DH        ;Get to last row on screen
  1043.         MOV    DL,PROMPT_LENGTH + 9
  1044.         CALL    ERASE_EOL    ;Erase to the end of this row
  1045.         MOV    AL,"O"        ;Write an "O"
  1046.         CMP    INSERT_MODE,0    ;In insert mode?
  1047.         JE    OVERSTRIKE
  1048.         MOV    AL,"I"        ;Write an "I"
  1049. OVERSTRIKE:
  1050.         DEC    DI        ;Backup one character position
  1051.         DEC    DI
  1052.         CALL    WRITE_NORMAL
  1053.         POP    DS
  1054.         RET
  1055. REDO_PROMPT    ENDP
  1056.  
  1057. ;-----------------------------------------------------------------------
  1058. ; This displays the file buffer on the screen.
  1059. ;-----------------------------------------------------------------------
  1060. DISPLAY_SCREEN    PROC    NEAR
  1061.         ASSUME    DS:FILE_SEG, ES:FILE_SEG
  1062.         MOV    SI,TOP_OF_SCREEN;Point to first char on screen
  1063.         XOR    DH,DH        ;Start at first row
  1064.         JMP    SHORT NEXT_ROW
  1065. DISPLAY_BOTTOM:                ;This redraws the bottom only
  1066.         CALL    FIND_START    ;Find first character on this row
  1067.         MOV    DX,CUR_POSN    ;Get current cursor row
  1068. NEXT_ROW:
  1069.         PUSH    DX
  1070.         CALL    DISPLAY_LINE    ;Display a line
  1071.         POP    DX
  1072.         INC    DH        ;Move to the next row
  1073.         CMP    DH,ROWS        ;At end of screen yet?
  1074.         JBE    NEXT_ROW    ;Do all the rows
  1075.         RET
  1076. DISPLAY_SCREEN    ENDP
  1077.  
  1078. ;-----------------------------------------------------------------------
  1079. ; This subroutine displays a single line to the screen. DH holds the 
  1080. ; row number, SI has the offset into the file buffer. Tabs are expanded.
  1081. ; Adjustment is made for side shift.
  1082. ;-----------------------------------------------------------------------
  1083. DISPLAY_CURRENT    PROC    NEAR
  1084.         CALL    FIND_START
  1085.         MOV    DX,CUR_POSN
  1086. DISPLAY_LINE:
  1087.         XOR    DL,DL        ;Start at column zero
  1088.         MOV    MARGIN_COUNT,DL
  1089.         MOV    CX,DX        ;Use CL to count the columns
  1090.         CALL    POSITION    ;Compute offset into video
  1091. NEXT_CHAR:
  1092.         CMP    SI,LAST_CHAR    ;At end of file?
  1093.         JAE    LINE_DONE
  1094.         LODSB            ;Get next character
  1095.         CMP    AL,CR        ;Is it a carriage return?
  1096.         JE    FOUND_CR    ;Quit when a CR is found
  1097.         CMP    AL,TAB        ;Is this a Tab character
  1098.         JE    EXPAND_TAB    ;If yes, expand to spaces
  1099.         CALL    PUT_CHAR    ;Put character onto screen
  1100. TAB_DONE:
  1101.         CMP    CL,COLUMNSB    ;At right edge of screen?
  1102.         JB    NEXT_CHAR
  1103.         CMP    BYTE PTR [SI],CR;Is this the end of the line?
  1104.         JE    NOT_BEYOUND
  1105.         DEC    DI        ;Backup one character
  1106.         DEC    DI
  1107.         MOV    AL,4        ;Show a diamond
  1108.         CALL    WRITE_INVERSE    ;In inverse video
  1109. NOT_BEYOUND:
  1110.         JMP    FIND_NEXT    ;Find start of next line
  1111. FOUND_CR:
  1112.         LODSB            ;Look at the next character
  1113.         CMP    AL,LF        ;Is it a line feed?
  1114.         JE    LINE_DONE
  1115.         DEC    SI
  1116. LINE_DONE:
  1117.         MOV    DX,CX
  1118.         JMP    ERASE_EOL    ;Erase the rest of the line
  1119. EXPAND_TAB:
  1120.         MOV    AL," "        ;Convert Tabs to spaces
  1121.         CALL    PUT_CHAR
  1122.         MOV    AL,MARGIN_COUNT
  1123.         ADD    AL,CL
  1124.         TEST    AL,00000111B    ;At even multiple of eight?
  1125.         JNZ    EXPAND_TAB    ;If not keep adding spaces
  1126.         JMP    TAB_DONE
  1127. DISPLAY_CURRENT    ENDP
  1128.  
  1129. ;-----------------------------------------------------------------------
  1130. ; This displays a single character to the screen.  If the character is 
  1131. ; marked, it is shown in inverse video.  Characters outside the current
  1132. ; margin are not displayed. Characters left of the margin are skipped.
  1133. ;-----------------------------------------------------------------------
  1134. PUT_CHAR    PROC    NEAR
  1135.         MOV    BL,MARGIN_COUNT    ;Get distance to left margin
  1136.         CMP    BL,LEFT_MARGIN    ;Are we inside left margin?
  1137.         JAE    IN_WINDOW    ;If yes, show the character
  1138.         INC    BL
  1139.         MOV    MARGIN_COUNT,BL
  1140.         RET
  1141. IN_WINDOW:
  1142.         CMP    SI,MARK_START    ;Is this character marked?
  1143.         JBE    NOT_MARKED
  1144.         CMP    SI,MARK_END
  1145.         JA    NOT_MARKED
  1146.         CALL    WRITE_INVERSE    ;Marked characters shown inverse
  1147.         JMP    SHORT NEXT_COL
  1148. NOT_MARKED:
  1149.         CALL    WRITE_NORMAL
  1150. NEXT_COL:
  1151.         INC    CL        ;Increment the column count
  1152.         RET
  1153. PUT_CHAR    ENDP
  1154.  
  1155. ;-----------------------------------------------------------------------
  1156. ; This routine adds a character into the file.  In insert mode, remaining
  1157. ; characters are pushed forward. If a CR is inserted, a LF is added also.
  1158. ;-----------------------------------------------------------------------
  1159. INSERT_KEY    PROC    NEAR
  1160.         MOV    SI,CURSOR
  1161.         CMP    AL,CR        ;Was this a carriage return
  1162.         JE    NEW_LINE
  1163.  
  1164.         MOV    SI,CURSOR
  1165.         CMP    INSERT_MODE,0    ;In insert mode?
  1166.         JNE    INSERT_CHAR
  1167.         CMP    BYTE PTR [SI],CR;At end of line?
  1168.         JE    INSERT_CHAR
  1169.         CMP    SI,LAST_CHAR    ;At end of file?
  1170.         JE    INSERT_CHAR
  1171.         MOV    DI,SI
  1172.         XCHG    DS:[SI],AL    ;Switch new character for old one
  1173.         CALL    SAVE_CHAR    ;Store the old character
  1174.         JMP    SHORT ADVANCE
  1175. INSERT_CHAR:
  1176.         PUSH    SI
  1177.         PUSH    AX        ;Save the new character
  1178.         MOV    AX,1
  1179.         CALL    OPEN_SPACE    ;Make room for it
  1180.         POP    AX        ;Get back the new character
  1181.         POP    DI
  1182.         JC    FILE_FULL
  1183.         STOSB            ;Insert character in file buffer
  1184. ADVANCE:
  1185.         OR    DIRTY_BITS,4    ;Current line is dirty
  1186.         PUSH    UNDO_LENGTH
  1187.         CALL    RIGHT        ;Move cursor to next letter
  1188.         POP    UNDO_LENGTH
  1189. FILE_FULL:
  1190.         RET
  1191. NEW_LINE:
  1192.         PUSH    SI
  1193.         MOV    AX,2
  1194.         CALL    OPEN_SPACE    ;Make space for CR and LF
  1195.         POP    DI        ;Get back old cursor location
  1196.         JC    FILE_FULL
  1197.         MOV    AX,LF*256+CR
  1198.         STOSW            ;Store the CR and LF
  1199.         CALL    DISPLAY_BOTTOM    ;Repaint bottom of the screen
  1200.         CALL    HOME        ;Cursor to start of line
  1201.         JMP    DOWN        ;Move down to the new line
  1202. INSERT_KEY    ENDP
  1203.  
  1204. ;-----------------------------------------------------------------------
  1205. ; This subroutine inserts spaces into the file buffer.  On entry AX
  1206. ; contains the number of spaces to be inserted.  On return, CF=1 if
  1207. ; there was not enough space in the file buffer.
  1208. ;-----------------------------------------------------------------------
  1209. OPEN_SPACE    PROC    NEAR
  1210.         MOV    CX,LAST_CHAR    ;Last character in the file
  1211.         MOV    SI,CX
  1212.         MOV    DI,CX
  1213.         ADD    DI,AX        ;Offset for new end of file
  1214.         JC    NO_ROOM        ;If no more room, return error
  1215.         MOV    LAST_CHAR,DI    ;Save offset of end of file
  1216.         SUB    CX,CURSOR    ;Number of characters to shift
  1217.         DEC    DI
  1218.         DEC    SI
  1219.         STD            ;String moves goes forward
  1220.         REP    MOVSB        ;Shift the file upward
  1221.         CLD
  1222.         CLC
  1223. NO_ROOM:
  1224.         RET
  1225. OPEN_SPACE    ENDP
  1226.  
  1227. ;-----------------------------------------------------------------------
  1228. ; This subroutine adjusts the cursor position ahead to the saved cursor
  1229. ; column.  On entry DH has the cursor row.
  1230. ;-----------------------------------------------------------------------
  1231. SHIFT_RIGHT    PROC    NEAR
  1232.         MOV    CL,SAVE_COLUMN    ;Keep the saved cursor offset
  1233.         XOR    CH,CH
  1234.         MOV    BP,CX        ;Keep the saved cursor position
  1235.         ADD    CL,LEFT_MARGIN    ;Shift into visable window also
  1236.         ADC    CH,0
  1237.         XOR    DL,DL
  1238.         MOV    CUR_POSN,DX    ;Get cursor row/column
  1239.         JCXZ    NO_CHANGE
  1240. RIGHT_AGAIN:
  1241.         PUSH    CX
  1242.         CMP    BYTE PTR [SI],CR;At end of line?
  1243.         JE    DONT_MOVE    ;If at end, stop moving
  1244.         CALL    RIGHT        ;Move right one character
  1245. DONT_MOVE:
  1246.         POP    CX
  1247.  
  1248.         MOV    AL,SAVE_COLUMN
  1249.         XOR    AH,AH
  1250.         CMP    AX,CX        ;Is cursor still in margin?
  1251.         JL    IN_MARGIN    ;If yes, keep moving
  1252.  
  1253.         MOV    DX,CUR_POSN    ;Get cursor column again
  1254.         XOR    DH,DH
  1255.         CMP    DX,BP        ;At saved cursor position?
  1256.         JE    RIGHT_DONE    ;If yes, were done
  1257.         JA    RIGHT_TOO_FAR    ;Did we go too far?
  1258. IN_MARGIN:
  1259.         LOOP    RIGHT_AGAIN
  1260. RIGHT_DONE:
  1261.         MOV    CX,BP
  1262.         MOV    SAVE_COLUMN,CL    ;Get back saved cursor position
  1263. NO_CHANGE:
  1264.         RET
  1265. RIGHT_TOO_FAR:
  1266.         CALL    LEFT        ;Move back left one place
  1267.         MOV    CX,BP
  1268.         MOV    SAVE_COLUMN,CL    ;Get back saved cursor position
  1269.         RET
  1270. SHIFT_RIGHT    ENDP
  1271.  
  1272. ;-----------------------------------------------------------------------
  1273. ; This subroutine skips past the CR and LF at SI.  SI returns new offset
  1274. ;-----------------------------------------------------------------------
  1275. SKIP_CR_LF    PROC    NEAR
  1276.         CMP    SI,LAST_CHAR    ;At last char in the file?
  1277.         JAE    NO_SKIP        ;If yes, dont skip anything
  1278.         CMP    BYTE PTR [SI],CR;Is first character a CR?
  1279.         JNE    NO_SKIP
  1280.         INC    SI        ;Look at next character
  1281.         CMP    SI,LAST_CHAR    ;Is it at the end of file?
  1282.         JAE    NO_SKIP        ;If yes, dont skip anymore
  1283.         CMP    BYTE PTR [SI],LF;Is next character a line feed?
  1284.         JNE    NO_SKIP        ;Skip any line feeds also
  1285.         INC    SI
  1286. NO_SKIP:
  1287.         RET
  1288. SKIP_CR_LF    ENDP
  1289.  
  1290. ;-----------------------------------------------------------------------
  1291. ; This subroutine finds the beginning of the previous line.
  1292. ;-----------------------------------------------------------------------
  1293. FIND_PREVIOUS    PROC    NEAR
  1294.         PUSH    CURSOR        ;Save the cursor location
  1295.         CALL    FIND_CR        ;Find start of this line
  1296.         MOV    CURSOR,SI    ;Save the new cursor
  1297.         CALL    FIND_START    ;Find the start of this line
  1298.         POP    CURSOR        ;Get back starting cursor
  1299.         RET
  1300. FIND_PREVIOUS    ENDP
  1301.  
  1302. ;-----------------------------------------------------------------------
  1303. ; This searches for the previous carriage return.  Search starts at SI.
  1304. ;-----------------------------------------------------------------------
  1305. FIND_CR        PROC    NEAR
  1306.         PUSH    CX
  1307.         MOV    AL,CR        ;Look for a carriage return
  1308.         MOV    DI,SI
  1309.         MOV    CX,SI
  1310.         JCXZ    AT_BEGINNING
  1311.         DEC    DI
  1312.         STD            ;Search backwards
  1313.         REPNE    SCASB        ;Scan for the character
  1314.         CLD            ;Restore direction flag
  1315.         INC    DI
  1316.         MOV    SI,DI
  1317. AT_BEGINNING:
  1318.         POP    CX
  1319.         RET
  1320. FIND_CR        ENDP
  1321.  
  1322. ;-----------------------------------------------------------------------
  1323. ; This subroutine computes the location of the start of current line.
  1324. ; Returns SI pointing to the first character of the current line.
  1325. ;-----------------------------------------------------------------------
  1326. FIND_START    PROC    NEAR
  1327.         MOV    SI,CURSOR    ;Get the current cursor
  1328.         OR    SI,SI        ;At start of the file?
  1329.         JZ    AT_START    ;If yes, were done
  1330.         CALL    FIND_CR        ;Find the 
  1331.         CALL    SKIP_CR_LF
  1332. AT_START:
  1333.         RET
  1334. FIND_START    ENDP
  1335.  
  1336. ;-----------------------------------------------------------------------
  1337. ; This finds the offset of the start of the next line.  The search is 
  1338. ; started at location ES:SI.  On return CF=1 of no CR was found.
  1339. ;-----------------------------------------------------------------------
  1340. FIND_NEXT    PROC    NEAR
  1341.         PUSH    CX
  1342.         CALL    FIND_EOL    ;Find the end of this line
  1343.         JC    AT_NEXT        ;If at end of file, return
  1344.         CALL    SKIP_CR_LF    ;Skip past CR and LF
  1345.         CLC            ;Indicate end of line found
  1346. AT_NEXT:                  
  1347.         POP    CX
  1348.         RET
  1349. FIND_NEXT    ENDP
  1350.  
  1351. ;-----------------------------------------------------------------------
  1352. ; This searches for the next carriage return in the file.  The search
  1353. ; starts at the offset in register SI.
  1354. ;-----------------------------------------------------------------------
  1355. FIND_EOL    PROC    NEAR
  1356.         MOV    AL,CR        ;Look for a carriage return
  1357.         MOV    CX,LAST_CHAR    ;Last letter in the file
  1358.         SUB    CX,SI        ;Count for the search
  1359.         MOV    DI,SI
  1360.         JCXZ    AT_END        ;If nothing to search, return
  1361.         REPNE    SCASB        ;Scan for the character
  1362.         MOV    SI,DI        ;Return the location of the CR
  1363.         JCXZ    AT_END        ;If not found, return
  1364.         DEC    SI
  1365.         CLC            ;Indicate the CR was found
  1366.         RET
  1367. AT_END:
  1368.         STC            ;Indicate CR was not found
  1369.         RET
  1370. FIND_EOL    ENDP
  1371.  
  1372. ;-----------------------------------------------------------------------
  1373. ; This subroutine positions the screen with the cursor at the row
  1374. ; selected in register DH.  On entry, SI holds the cursor offset.
  1375. ;-----------------------------------------------------------------------
  1376. LOCATE        PROC    NEAR
  1377.         MOV    CL,DH
  1378.         XOR    CH,CH
  1379.         MOV    CURSOR,SI
  1380.         XOR    DX,DX        ;Start at top of the screen
  1381.         OR    SI,SI        ;At start of buffer?
  1382.         JZ    LOCATE_FIRST
  1383.  
  1384.         CALL    FIND_START    ;Get start of this row
  1385.         XOR    DX,DX        ;Start at top of the screen
  1386.         OR    SI,SI        ;Is cursor at start of file?
  1387.         JZ    LOCATE_FIRST
  1388.         JCXZ    LOCATE_FIRST    ;If locating to top row were done
  1389. FIND_TOP:
  1390.         PUSH    SI
  1391.         PUSH    CX
  1392.         CALL    FIND_CR        ;Find previous row
  1393.         POP    CX
  1394.         POP    AX
  1395.         CMP    BYTE PTR [SI],CR
  1396.         JNE    LOCATE_FIRST
  1397.         CMP    SI,AX        ;Did it change?
  1398.         JE    LOCATE_DONE    ;If not, quit moving
  1399.         INC    DH        ;Cursor moves to next row
  1400.         LOOP    FIND_TOP
  1401.  
  1402. LOCATE_DONE:
  1403.         PUSH    CURSOR
  1404.         MOV    CURSOR,SI
  1405.         CALL    FIND_START    ;Find start of top of screen
  1406.         POP    CURSOR
  1407. LOCATE_FIRST:
  1408.         MOV    TOP_OF_SCREEN,SI
  1409.         MOV    CUR_POSN,DX
  1410.         CALL    CURSOR_COL
  1411.         MOV    SAVE_COLUMN,DL
  1412.         RET
  1413. LOCATE        ENDP
  1414.  
  1415. ;-----------------------------------------------------------------------
  1416. ; This subroutine computes the correct column for the cursor.  No
  1417. ; inputs.  On exit, CUR_POSN is set and DX has the row/column.
  1418. ;-----------------------------------------------------------------------
  1419. CURSOR_COL    PROC    NEAR
  1420.         MOV    SI,CURSOR    ;Get cursor offset
  1421.         CALL    FIND_START    ;Find start of this line
  1422.         MOV    CX,CURSOR
  1423.         SUB    CX,SI
  1424.         MOV    DX,CUR_POSN    ;Get current row
  1425.         XOR    DL,DL        ;Start at column zero
  1426.         MOV    MARGIN_COUNT,DL    ;Count past the left margin
  1427.         JCXZ    COL_DONE
  1428. CURSOR_LOOP:
  1429.         LODSB            ;Get the next character
  1430.         CMP    AL,CR        ;Is it the end of line?
  1431.         JE    COL_DONE    ;If end, were done
  1432.         CMP    AL,TAB        ;Is it a tab?
  1433.         JNE    NOT_A_TAB
  1434.  
  1435.         MOV    BL,MARGIN_COUNT
  1436.         OR    BL,00000111B
  1437.         MOV    MARGIN_COUNT,BL
  1438.         CMP    BL,LEFT_MARGIN    ;Inside visible window yet?
  1439.         JB    NOT_A_TAB    ;If not, don't advance cursor
  1440.         OR    DL,00000111B    ;Move to multiple of eight
  1441. NOT_A_TAB:
  1442.         MOV    BL,MARGIN_COUNT
  1443.         INC    BL
  1444.         MOV    MARGIN_COUNT,BL
  1445.         CMP    BL,LEFT_MARGIN
  1446.         JBE    OUT_OF_WINDOW
  1447.         INC    DL        ;Were at next column now
  1448. OUT_OF_WINDOW:
  1449.         LOOP    CURSOR_LOOP
  1450. COL_DONE:
  1451.         CMP    DL,COLUMNSB    ;Past end of display?
  1452.         JB    COLUMN_OK    ;If not, were OK?
  1453.         MOV    DL,COLUMNSB
  1454.         DEC    DL        ;Leave cursor at last column
  1455. COLUMN_OK:
  1456.         MOV    CUR_POSN,DX    ;Store the row/column
  1457.         RET
  1458. CURSOR_COL    ENDP
  1459.  
  1460. ;-----------------------------------------------------------------------
  1461. ; This displays the string at CS:SI at the location in DX.  The 
  1462. ; remainder of the row is erased.  Cursor is put at the end of the line.
  1463. ;-----------------------------------------------------------------------
  1464. TTY_STRING    PROC    NEAR
  1465.         ASSUME    DS:CSEG
  1466.         PUSH    DX
  1467.         CALL    POSITION    ;Compute offset into video
  1468.         POP    DX
  1469. TTY_LOOP:
  1470.         LODSB
  1471.         OR    AL,AL        ;At end of string yet?
  1472.         JZ    TTY_DONE
  1473.         INC    DL
  1474.         PUSH    DX
  1475.         CALL    WRITE_INVERSE    ;Write in inverse video
  1476.         POP    DX
  1477.         JMP    TTY_LOOP
  1478. TTY_DONE:
  1479.         CALL    SET_CURSOR    ;Move cursor to end of string
  1480.         JMP    ERASE_EOL    ;Erase the rest of line
  1481. TTY_STRING    ENDP
  1482.  
  1483. ;-----------------------------------------------------------------------
  1484. ; This copies the input filename to CS:DI and changes the extension
  1485. ;-----------------------------------------------------------------------
  1486. CHG_EXTENSION    PROC    NEAR
  1487.         ASSUME    DS:CSEG, ES:CSEG
  1488.  
  1489.         PUSH    SI
  1490.         MOV    SI,NAME_POINTER
  1491. CHG_LOOP:
  1492.         LODSB        
  1493.         CMP    AL,"."        ;Look for the extension
  1494.         JE    FOUND_DOT
  1495.         OR    AL,AL
  1496.         JZ    FOUND_DOT
  1497.         STOSB            ;Copy a character
  1498.         JMP    CHG_LOOP
  1499. FOUND_DOT:
  1500.         MOV    CX,5        ;Five chars in extension
  1501.         POP    SI
  1502.         REP    MOVSB        ;Move new extension in
  1503.         RET
  1504. CHG_EXTENSION    ENDP
  1505.  
  1506. ;-----------------------------------------------------------------------
  1507. ; This is the control break handler.  It ignores the break.
  1508. ;-----------------------------------------------------------------------
  1509. NEWINT23    PROC    FAR
  1510.         ASSUME    DS:NOTHING, ES:NOTHING
  1511.         MOV    CS:DIRTY_BITS,1
  1512.         CLC            ;Tell DOS to ignore break
  1513.         IRET
  1514. NEWINT23    ENDP
  1515.  
  1516. ;-----------------------------------------------------------------------
  1517. ; This is the severe error handler.  It homes the cursor before 
  1518. ; processing the error.
  1519. ;-----------------------------------------------------------------------
  1520. NEWINT24    PROC    FAR
  1521.         ASSUME    DS:NOTHING, ES:NOTHING
  1522.         PUSHF
  1523.         PUSH    AX
  1524.         PUSH    BX
  1525.         PUSH    DX
  1526.         MOV    CS:DIRTY_BITS,1
  1527.         XOR    DX,DX
  1528.         CALL    SET_CURSOR    ;Put cursor at home
  1529.         POP    DX
  1530.         POP    BX
  1531.         POP    AX
  1532.         POPF
  1533.         JMP    CS:OLDINT24
  1534. NEWINT24    ENDP
  1535. ;-----------------------------------------------------------------------
  1536. EVEN
  1537. NAME_DOT_$$$    EQU    $
  1538. NAME_DOT_BAK    EQU    $ + 80H
  1539. UNDO_BUFFER    EQU    $ + 100H
  1540. LINE_BUFFER    EQU    $ + 200H
  1541. NEW_STACK    EQU    $ + 500H
  1542. CSEG        ENDS
  1543. ;-----------------------------------------------------------------------
  1544. FILE_SEG    SEGMENT
  1545. FILE_SEG    ENDS
  1546. END        START
  1547.